package com.carnation.service.impl;

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.commons.net.ftp.FTP;
import org.apache.commons.net.ftp.FTPClient;
import org.apache.commons.net.ftp.FTPFile;
import org.apache.log4j.Logger;

import com.carnation.bean.FTPFileInfo;
import com.carnation.service.FTPServer;
import com.carnation.utils.MenuFileUtril;

public class FTPServerImpl implements FTPServer{

	private FTPClient ftpclient = null;
	private Logger logger = Logger.getLogger(FTPServerImpl.class);
	MenuFileUtril menuFileUtril = new MenuFileUtril();
	
	private FTPClient getFTPClient(){
		if(ftpclient == null){
			try {
				ftpclient = new FTPClient();
				ftpclient.connect(menuFileUtril.getFTPHost(), menuFileUtril.getFTPPort());
				ftpclient.login(menuFileUtril.getFTPUser(), menuFileUtril.getFTPPasswd());
				ftpclient.setFileType(FTP.BINARY_FILE_TYPE);
				if(ftpclient.isConnected()){
					logger.info("FTP链接成功");
				}
				return ftpclient;
			} catch (IOException e) {
				return null;
			}
		}
		else{
			return ftpclient;
		}
	}
	
	@Override
	public void uploadFile(String path, String localName,String ftpName) {
		// TODO Auto-generated method stub
		try {
			ftpclient = getFTPClient();
			ftpclient.changeWorkingDirectory(path);
			String encodingName = new String(ftpName.getBytes(ftpclient.getCharset()),ftpclient.getControlEncoding());
			OutputStream out = ftpclient.appendFileStream(encodingName);
			InputStream is = new FileInputStream(localName);
			byte[] buff = new byte[1024*256];
			int read = -1;
			do{
				if(out != null){
					read = is.read(buff);
					if(read > 0){
						out.write(buff,0,read);
					}
				}
			}while(read > 0);
			is.close();
			out.flush();
			out.close();
			if(ftpclient.completePendingCommand()){
				logger.info("上传成功");
			}
			else{
				logger.info("上传失败");
			}
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

	@Override
	public void downloadFile(String path, String ftpName, String localfile) {
		// TODO Auto-generated method stub
		ftpclient = getFTPClient();
		try {
			ftpclient.changeWorkingDirectory(path);
			InputStream is = ftpclient.retrieveFileStream(ftpName);
			OutputStream out = new FileOutputStream(localfile);
			byte[] buff = new byte[1024 *256];
			int read = -1;
			do{
				if(is != null){
					read = is.read(buff);
					if(read > 0){
						out.write(buff,0,read);
					}
					out.flush();
				}
			}while(read > 0);
			is.close();
			out.close();
			if(ftpclient.completePendingCommand()){
				logger.info("下载成功");
			}
			else{
				logger.info("下载失败");
			}
		} catch (IOException e) {
			// TODO Auto-generated catch block
			logger.info("下载时产生异常",e);
		}
	}

	
	@Override
	public void close() {
		// TODO Auto-generated method stub
		if(ftpclient.isAvailable()){
			try {
				ftpclient.disconnect();
				ftpclient.abort();
			} catch (IOException e) {
				logger.error("关闭连接出错",e);
			}
		}
	}

	@Override
	public boolean mkdir(String path, String directoryName) {
		// TODO Auto-generated method stub
		try{
			ftpclient = getFTPClient();
			ftpclient.changeWorkingDirectory(path);
			int code;
			code = ftpclient.mkd(directoryName);
			if(code == 257){
				return true;
			}
			else{
				return false;
			}
		}
		catch(IOException e){
			logger.error("创建新的目录出错",e);
			return false;
		}		
	}

	@Override
	public boolean rmdir(String path, String directoryName) {
		// TODO Auto-generated method stub
		try {
			ftpclient = getFTPClient();
			ftpclient.changeWorkingDirectory(path);
			int code;
			code = ftpclient.rmd(directoryName);
			logger.info(code);
		} catch (IOException e) {
			// TODO Auto-generated catch block
			logger.info("删除目录出错",e);
		}
		return false;
	}

	@Override
	public List<FTPFileInfo> getFtpFileInfoByParent(String path) {
		// TODO Auto-generated method stub
		List<FTPFileInfo> list = new ArrayList<FTPFileInfo>();
		FTPFileInfo parent = new FTPFileInfo();
		parent.setFileName("..");
		list.add(parent);
		ftpclient = getFTPClient();
		try {
			ftpclient.changeWorkingDirectory(path);
			FTPFile[] files = ftpclient.listFiles();
			SimpleDateFormat format = new SimpleDateFormat("yyyy-mm-dd HH:mm:ss");
			System.out.println("系统编码:" + ftpclient.getControlEncoding());
			System.out.println("客服端编码:" + ftpclient.getCharsetName());
			for(FTPFile file : files){
				if(!file.getName().startsWith(".")){
					System.out.println("编码转换前的filename:" + file.getName());
					String filename = new String(file.getName().getBytes(ftpclient.getControlEncoding()),"UTF-8");
					System.out.println("编码转换后的filename:" + filename);
					FTPFileInfo fileInfo = new FTPFileInfo(filename, 
							file.getUser(), file.getGroup(), 
							file.getSize(), getType(file.getType()),
							format.format(file.getTimestamp().getTime()), file.getRawListing().split(" ")[0]);
					list.add(fileInfo);
				}
			}
			return list;
		} catch (IOException e) {
			// TODO Auto-generated catch block
			logger.error("获取目录下个文件的信息",e);
			return list;
		}
	}

	private String getType(int type){
		if(type == 0){
			return "文件";
		}
		else if (type == 1) {
			return "文件夹";
		}
		else{
			return "未知文件类型";
		}
	}

	@Override
	public Map<String,Long> findRegularFileList(String path) {
		Map<String, Long> map = new HashMap<String, Long>();
		ftpclient = getFTPClient();
		try {
			ftpclient.changeWorkingDirectory(path);
			FTPFile[] files = ftpclient.listFiles();
			for(FTPFile f :files){
				if(f.isFile()){
					map.put(f.getName(), f.getSize());
				}
			}
			return map;
		} catch (IOException e) {
			return new HashMap<String, Long>();
		}
	}

	@Override
	public String getPath(String path) throws IOException {
		ftpclient = getFTPClient();
		try{
			ftpclient.changeWorkingDirectory(menuFileUtril.getFTPStorePath());
		}
		catch(Exception e){
			e.printStackTrace();
		}
		String[] p = path.split("/");
		for(int i =0;i<p.length;i++){
			ftpclient.changeWorkingDirectory(p[i]);
		}
		
		return ftpclient.printWorkingDirectory();
	}

	@Override
	public InputStream findFileStreamByRealPathAndFileName(String realpath,
			String filename) {
		ftpclient = getFTPClient();
		try{
			ftpclient.changeWorkingDirectory(realpath);
			String file = new String(filename.getBytes(ftpclient.getCharset()),ftpclient.getControlEncoding());
			return ftpclient.retrieveFileStream(file);
		}
		catch(Exception e){
			e.printStackTrace();
			return null;
		}
	}

	/**
	 * 
	 * @param path
	 * @param fileName
	 * @return 404 没有找到对应的文件或文件下
	 *         400 删除失败
	 *         500 系统发生异常出错
	 *         304 文件夹下存在文件或文件夹，不允许删除
	 *         200 删除成功
	 */
	@Override
	public String deleteFile(String path, String fileName) {
		ftpclient = getFTPClient();
		try {
			String name = new String(fileName.getBytes(ftpclient.getCharset()),ftpclient.getControlEncoding());
			ftpclient.changeWorkingDirectory(path);
			FTPFile[] ftpFiles = ftpclient.listFiles();
			FTPFile target = null;
			for(FTPFile f : ftpFiles){
				if (f.getName().equals(name)) {
					target = f;
					break;
				}
			}
			if(target == null ){
				return "404";
			}
			else{
				if(target.isDirectory()){
					ftpclient.changeWorkingDirectory(target.getName());
					if(ftpclient.listFiles().length == 0){
						ftpclient.changeToParentDirectory();
						if(ftpclient.removeDirectory(target.getName())){
							return "200";
						}
						else{
							return "400";
						}
					}
					else{
						logger.info("文件夹下有文件,不允许删除");
						return "304";
					}
				}
				else if(target.isFile()){
					if(ftpclient.deleteFile(target.getName())){
						return "200";
					}
					else{
						return "400";
					}
				}
				else{
					logger.info("未知类型，不删除");
					return "400";
				}
			}
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			return "500";
		}
	}

}
